﻿using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Text;

using BizElements.Core;

namespace BizElements.Generator
{
    public partial class MySqlConnCtl : UserControl, IMetaDataSourceUi
    {
        public MySqlConnCtl()
        {
            InitializeComponent();
        }

        #region Parse and test metadata source.

        private void uiConnect_Click(object sender, EventArgs e)
        {
            CreateAndTestNewMetaDataSource();
        }

        private void CreateAndTestNewMetaDataSource()
        {
            DisposeCurrentMetaDataSource();
            var connStr = ParseConnectionString();
            if (connStr == null)
                return;

            this.MetaDataSource = DbGeneratorComponentFactory.GetMetadataSource(this.dbms, connStr.Build());
            bool isTestOk = TestConnection();
            if (isTestOk)
            {
                FireConnected();
                this.uiConnect.Enabled = false;
                this.uiDisconnect.Enabled = true;
            }
            else
            {
                this.MetaDataSource = null;
            }
        }

        private MySqlConnStringBuilder ParseConnectionString()
        {
            MySqlConnStringBuilder builder = new MySqlConnStringBuilder()
            {
                Server = this.uiServer.Text.Trim(),
                Database = this.uiDatabase.Text.Trim(),
                UserId = this.uiUserId.Text.Trim(),
                Password = this.uiPassword.Text.Trim()
            };

            string[] errors = builder.Validate();
            if (errors.Length > 0)
            {
                builder = null;
                string errmsg = string.Join(Environment.NewLine, errors);
                MessageBox.Show(errmsg);
            }

            return builder;
        }

        private bool TestConnection()
        {
            try
            {
                this.Cursor = Cursors.AppStarting;
                this.MetaDataSource.OpenConnection();
                this.MetaDataSource.CloseConnection();
                return true;
            }
            catch (Exception ex)
            {
                string errmsg = Messages.MySqlConnCtl_CannotConnectToDatabase + Environment.NewLine + ex.ToString();
                MessageBox.Show(errmsg, Messages.Error, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
            finally
            {
                this.Cursor = Cursors.Default;
            }
        }

        private void FireConnected()
        {
            if (this.Connected != null)
                Connected(this, new MetaDataSourceEventArgs(this.MetaDataSource));
        }

        #endregion

        #region Disconnect and dispose metadata source.

        private void uiDisconnect_Click(object sender, EventArgs e)
        {
            DisconnectAndDisposeCurrentMetaDataSource();
        }

        private void DisconnectAndDisposeCurrentMetaDataSource()
        {
            DisposeCurrentMetaDataSource();
            this.uiConnect.Enabled = true;
            this.uiDisconnect.Enabled = false;
            FireDisconnected();
        }

        private void FireDisconnected()
        {
            if (this.Disconnected != null)
                Disconnected(this, null);
        }

        private void DisposeCurrentMetaDataSource()
        {
            if (this.MetaDataSource != null)
            {
                this.MetaDataSource.CloseConnection();
                this.MetaDataSource = null;
            }
        }

        #endregion

        #region IMetaDataSourceUi Members.

        [Browsable(false)]
        public UserControl Control
        {
            get { return this; }
        }

        [Browsable(false)]
        public IMetadataSource MetaDataSource { get; private set; }

        DbmsType dbms = DbmsType.MySql_5;

        public DbmsType Dbms
        {
            get { return this.dbms; }
            set
            {
                if (DbGeneratorComponentFactory.IsMySql(value))
                    this.dbms = value;
                else
                    throw new ArgumentException(Messages.MySqlConnCtl_OnlyMySqlDBMSsAreSupported);
            }
        }

        public event EventHandler<MetaDataSourceEventArgs> Connected;

        public event EventHandler<MetaDataSourceEventArgs> Disconnected;

        #endregion

        #region Settings.

        public void ReadSettings(BizElementsSettings settings)
        {
            DisconnectAndDisposeCurrentMetaDataSource();
            this.uiServer.Text = settings["MySqlConn_Server"];
            this.uiDatabase.Text = settings["MySqlConn_Database"];
            this.uiUserId.Text = settings["MySqlConn_UserId"];
            this.uiPassword.Text = settings["MySqlConn_Password"];
        }

        public void WriteSettings(BizElementsSettings settings)
        {
            settings["MySqlConn_Server"] = this.uiServer.Text.Trim();
            settings["MySqlConn_Database"] = this.uiDatabase.Text.Trim();
            settings["MySqlConn_UserId"] = this.uiUserId.Text.Trim();
            settings["MySqlConn_Password"] = this.uiPassword.Text.Trim();
        }

        #endregion

        sealed class MySqlConnStringBuilder
        {
            #region Properties.

            public string Server { get; set; }
            public string Database { get; set; }
            public string UserId { get; set; }
            public string Password { get; set; }

            #endregion

            #region Methods.

            public string[] Validate()
            {
                if (string.IsNullOrEmpty(this.Server) || string.IsNullOrEmpty(this.Database))
                    return new string[] { Messages.MySqlConnCtl_ServerAndDatabaseNamesAreRequired };

                if (string.IsNullOrEmpty(this.UserId) || string.IsNullOrEmpty(Password))
                    return new string[] { Messages.MySqlConnCtl_UserIdAndPwdAreRequired };

                return new string[0];
            }

            const string ConnStrVariableFormat = "{0}={1};";

            public string Build()
            {
                // Server=127.0.0.1;Database=northwind;Uid=root;Pwd=password;
                StringBuilder connectionString = new StringBuilder();
                connectionString.AppendFormat(ConnStrVariableFormat, "Server", this.Server);
                connectionString.AppendFormat(ConnStrVariableFormat, "Database", this.Database);
                connectionString.AppendFormat(ConnStrVariableFormat, "Uid", this.UserId);
                connectionString.AppendFormat(ConnStrVariableFormat, "Pwd", this.Password);

                return connectionString.ToString();
            }

            #endregion
        }
    }
}
